﻿Imports WumpusWorld_2._0.Domain
Imports System.Random  'Needed to randomize pits and wumpus
Imports System.Drawing.Color
Imports System.Drawing.Font
Imports System.Drawing.FontStyle
Imports System.Drawing.RotateFlipType
Imports WumpusWorld_2._0.Functions.Agent
Imports WumpusWorld_2._0.Domain.Settings
Imports MicrosoftResearch.Infer.Distributions   'Used for test with bernoulli varables
Imports MicrosoftResearch.Infer
Imports MicrosoftResearch.Infer.Models

'TODO:   out of bounds. To make logic possible
'TODO:  Insert walls


Namespace Functions

    Public Class GenerateWorld

#Region " Generate World, Pictures and lables "

        ''' <summary>
        ''' Generate the arrays
        ''' </summary>
        ''' <param name="settings"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function generateArray(ByVal settings As Settings)

            Dim grid As Integer = settings.gridSize
            Dim cellList(grid - 1, grid - 1) As Cell
            'Adding cells to our matrix of cells, containing the actual information about the world
            For x = 0 To grid - 1
                For y = 0 To grid - 1

                    Dim celle As Cell = New Cell

                    celle.xPos = x
                    celle.yPos = y
                    cellList(x, y) = celle

                Next
            Next

            Return cellList
        End Function

        ''' <summary>
        ''' This function generates the main gameboard. It places pits, wumpus and gold in the world-array
        ''' </summary>
        ''' <param name="settings"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        ''' 
        Public Function GenerateBoard(ByVal settings As Settings, ByVal cellList(,) As Cell)

            Dim grid As Integer = settings.gridSize

            'Dim b As Variable(Of Boolean) = Variable.Bernoulli(0.5)
            'MsgBox(b.ObservedValue)


            Dim randomNumber As Integer 'Used to make random numbers
            Dim rand As New Random

            For x = 0 To grid - 1
                For y = 0 To grid - 1
                    randomNumber = rand.Next(1 / settings.probPit) 'Generate a rundom number between 1 and random number = 1/prob(Pit)

                    If randomNumber = 0 And Not (x = 0 And y = cellList.GetLength(1) - 1) Then 'Avoids setting pit in 1.1. Pit is set when random number = 0 
                        cellList(x, y).hasPit = True
                        'Generates adjacent breezes
                        If x >= 1 Then
                            cellList(x - 1, y).hasBreeze = True
                        End If
                        If x <= cellList.GetLength(0) - 2 Then
                            cellList(x + 1, y).hasBreeze = True
                        End If
                        If y >= 1 Then
                            cellList(x, y - 1).hasBreeze = True
                        End If
                        If y <= cellList.GetLength(1) - 2 Then
                            cellList(x, y + 1).hasBreeze = True
                        End If
                    End If
                Next
            Next

            Dim setWumpus As Boolean = False 'Use this to make sure that the wumpus is set in the loop

            For x = 0 To grid - 1
                For y = 0 To grid - 1
                    randomNumber = rand.Next(1 / settings.probWumpus) 'Generate a rundom number between 1 and random number = 1/prob(wumpus)

                    If setWumpus = False And randomNumber = 0 And Not (x = 0 And y = cellList.GetLength(1) - 1) Then 'Avoids setting wumpus in 1.1
                        cellList(x, y).hasWumpus = True
                        'Set sdjacent stenches
                        If x >= 1 Then
                            cellList(x - 1, y).hasStench = True
                        End If
                        If x <= cellList.GetLength(0) - 2 Then
                            cellList(x + 1, y).hasStench = True
                        End If
                        If y >= 1 Then
                            cellList(x, y - 1).hasStench = True
                        End If
                        If y <= cellList.GetLength(1) - 2 Then
                            cellList(x, y + 1).hasStench = True
                        End If

                        setWumpus = True 'When the wumpus is set, the program exits the loop

                    End If

                Next
                If x = grid - 1 And setWumpus = False Then  ' Test whether wumpus has been randomly set 
                    x = 0                                   ' If not, then reset x to begin looping again
                End If
            Next

            'set gold
            Dim setGold As Boolean = False 'Use this to make sure that the gold is set 
            For x = 0 To grid - 1
                For y = 0 To grid - 1
                    randomNumber = rand.Next(1 / settings.probGold) 'Generate a rundom number between 1 and random number = 1/prob(gold)

                    If setGold = False And randomNumber = 0 And (Not x = 0 And Not y = cellList.GetLength(1) - 1) Then 'Avoids setting gold in 1.1
                        cellList(x, y).hasGold = True
                        cellList(x, y).hasGlitter = True

                        setGold = True 'When the gold is set, the program exits the loop

                    End If

                Next
                If x = grid - 1 And setGold = False Then  ' Test whether the gold has been randomly set 
                    x = 0                                   ' If not, then reset x to begin looping again
                End If
            Next

            Return cellList
        End Function

        ''' <summary>
        ''' Go through all cells of the gameboard and insert appropriate picture based on properties.This is a one-time happening in the start
        ''' </summary>
        ''' <param name="array"></param>
        ''' <param name="settings"></param>
        ''' <param name="agent"></param>
        ''' <remarks></remarks>
        Public Sub GeneratePictures(ByVal array(,) As Cell, ByVal settings As Settings, ByVal agent As Agent, ByVal panel As String)
            Dim picSize As New Size(settings.picSizeWidth, settings.picSizeHeight)

            For x = 0 To array.GetLength(0) - 1
                For y = 0 To array.GetLength(1) - 1

                    Dim pictureBOX As New PictureBox

                    pictureBOX.Size = picSize
                    pictureBOX.Image = GetPicture(array(x, y), agent) ' Code that picks the correct picture. This only sets the main picture. Breezes, Stench and glitter is set in setLables()
                    pictureBOX.BorderStyle = BorderStyle.FixedSingle
                    If panel = "KB" Then
                        pictureBOX.Parent = MainWindow.pnlKB
                    ElseIf panel = "World" Then
                        pictureBOX.Parent = MainWindow.pnlWumpusWorld
                    End If

                    pictureBOX.Location = New Point(10 + array(x, y).xPos * settings.picSizeWidth, 10 + array(x, y).yPos * settings.picSizeHeight) '10 in the start to be inside the panel frame
                    pictureBOX.Padding = New Padding(0, 0, 0, 0)

                    'PictureBox is added to the pictureBox property of the cell in the end
                    array(x, y).picBox = pictureBOX

                    SetLabels(array(x, y)) 'Breezes, Stench and glitter is here
                Next

            Next

        End Sub

#End Region

#Region "Update World and functions"
        ''' <summary>
        '''  Function that returns the correct picture depending on the cell properties
        ''' </summary>
        ''' <param name="cell"></param>
        ''' <param name="agent"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetPicture(ByVal cell As Cell, ByVal agent As Agent)

            Dim image As Object
            With (cell)

                If .hasAgent And .hasWumpus Then
                    If MainWindow.WumpusAlive Then
                        image = My.Resources.RIP
                    Else
                        If agent.hasArrow Then
                            If agent.hasGold Then
                                image = My.Resources.AgentGoldArmed
                            Else
                                image = My.Resources.AgentRight
                            End If

                        Else
                            If agent.hasGold Then
                                image = My.Resources.AgentGoldNotArmed
                            Else
                                image = My.Resources.AgentNoGun
                            End If
                        End If
                    End If


                ElseIf .hasAgent And .hasPit Then
                    image = My.Resources.RIP

                ElseIf .hasAgent And .hasGold Then
                    If agent.hasArrow Then
                        image = My.Resources.AgentOnGold
                    Else
                        image = My.Resources.AgentOnGoldNotArmed
                    End If

                ElseIf .hasWumpus And .hasPit And .hasGold Then
                    If MainWindow.WumpusAlive Then
                        image = My.Resources.WumpusPitGold
                    Else
                        image = My.Resources.WumpusDeadPitGold
                    End If

                ElseIf .hasWumpus And .hasGold Then
                    If MainWindow.WumpusAlive Then
                        image = My.Resources.WumpusGold
                    Else
                        image = My.Resources.WumpusDeadGold
                    End If
                ElseIf .hasWumpus And .hasPit Then
                    If MainWindow.WumpusAlive Then
                        image = My.Resources.PitWumpus
                    Else
                        image = My.Resources.WumpusDeadPit
                    End If
                ElseIf .hasPit And .hasGold Then
                    image = My.Resources.PitGold

                ElseIf .hasPit Then
                    image = My.Resources.PIT
                ElseIf .hasWumpus Then
                    If MainWindow.WumpusAlive Then
                        image = My.Resources.Wumpus
                    Else
                        image = My.Resources.WumpusDead
                    End If
                ElseIf .hasAgent Then
                    If agent.hasArrow Then
                        If agent.hasGold Then
                            image = My.Resources.AgentGoldArmed
                        Else
                            image = My.Resources.AgentRight
                        End If
                    Else
                        If agent.hasGold Then
                            image = My.Resources.AgentGoldNotArmed
                        Else
                            image = My.Resources.AgentNoGun
                        End If
                    End If
                ElseIf .hasGold Then
                    image = My.Resources.Gold
                Else
                    image = My.Resources.Blank
                End If
            End With

            Return image
        End Function

        ''' <summary>
        '''   Pictures get updated after the agent moves / reacts. This will originally only be used by The KB-array - Not the world- it does not need it
        ''' </summary>
        ''' <param name="array"></param>
        ''' <param name="agent"></param>
        ''' <remarks></remarks>
        Public Sub UpdatePictures(ByVal array(,) As Cell, ByVal agent As Agent, ByVal panel As String)
            For x = 0 To array.GetLength(0) - 1
                For y = 0 To array.GetLength(1) - 1

                    If panel = "KB" Then
                        array(x, y).picBox.Parent = MainWindow.pnlKB

                    ElseIf panel = "World" Then
                        array(x, y).picBox.Parent = MainWindow.pnlWumpusWorld

                    End If

                    array(x, y).picBox.Image = GetPicture(array(x, y), agent)

                    'Rotates Agent picture based on agents direction
                    If array(x, y).hasAgent Then

                        Select Case agent.Direction
                            Case AgentDirection.Down
                                array(x, y).picBox.Image.RotateFlip(RotateFlipType.Rotate90FlipNone)
                            Case AgentDirection.Left
                                array(x, y).picBox.Image.RotateFlip(RotateFlipType.Rotate180FlipNone)
                            Case AgentDirection.Up
                                array(x, y).picBox.Image.RotateFlip(RotateFlipType.Rotate270FlipNone)
                        End Select

                    End If
                    SetLabels(array(x, y))
                Next
            Next

        End Sub

        ''' <summary>
        '''  The method sets lables for breeze, stench and glitter, depending on cell properties
        ''' </summary>
        ''' <param name="cell"></param>
        ''' <remarks></remarks>
        Public Sub SetLabels(ByVal cell As Cell)

            Dim b, s, gl, v As Boolean

            With cell

                If .hasPit Then
                    .hasBreeze = False
                    .hasStench = False
                End If

                If .hasBreeze = True Then
                    b = True
                    cell.setBreezeLabel(b)
                Else
                    cell.setBreezeLabel(b)
                End If

                If .hasStench = True Then
                    If MainWindow.WumpusAlive Then
                        s = True
                        cell.setStenchLabel(s)
                    Else
                        cell.setStenchLabel(s)
                    End If

                End If

                If .hasGlitter = True Then
                    gl = True
                    cell.setGlitterLabel(gl)
                Else
                    cell.setGlitterLabel(gl)
                End If

                If .isVisited = True Then
                    v = True
                    cell.setVisitedLabel(v)
                Else
                    cell.setVisitedLabel(v)
                End If

            End With
        End Sub

        ''' <summary>
        ''' Inserts new knowledge (a newly discovered cell) from the gameboard and into the KB
        ''' </summary>
        ''' <param name="world"></param>
        ''' <param name="KB"></param>
        ''' <remarks></remarks>
        Public Sub updateKBInfo(ByVal world As Cells, ByVal KB As Cells)
            Dim activeCell As New Cell
            activeCell = KB.getActiveCell(KB.cellArray)

            With KB.cellArray(activeCell.xPos, activeCell.yPos)
                .hasBreeze = world.cellArray(activeCell.xPos, activeCell.yPos).hasBreeze
                .hasPit = world.cellArray(activeCell.xPos, activeCell.yPos).hasPit
                .hasStench = world.cellArray(activeCell.xPos, activeCell.yPos).hasStench
                .hasWumpus = world.cellArray(activeCell.xPos, activeCell.yPos).hasWumpus
                .hasGlitter = world.cellArray(activeCell.xPos, activeCell.yPos).hasGlitter
                .hasGold = world.cellArray(activeCell.xPos, activeCell.yPos).hasGold

            End With

        End Sub
#End Region

    End Class
End Namespace